import 'dart:convert';

import 'package:flustars_flutter3/flustars_flutter3.dart';
import 'package:flutter_deer/database/beans/config/res_zero_tube_entity.dart';
import 'package:flutter_deer/database/beans/get_config_guns_entity.dart';
import 'package:flutter_deer/database/beans/mqtt_msg_model.dart';
import 'package:flutter_deer/database/beans/shift/current_shift_entity.dart';
import 'package:flutter_deer/database/order_status.dart';
import 'package:flutter_deer/database/tables.dart';
import 'package:flutter_deer/mvvm/base_net_provider.dart';
import 'package:flutter_deer/net/dio_utils.dart';
import 'package:flutter_deer/net/http_api.dart';
import 'package:flutter_deer/res/constant.dart';
import 'package:flutter_deer/ui/cashier/provider/turn_shift_provider.dart';
import 'package:flutter_deer/util/print/print_manager.dart';
import 'package:flutter_deer/util/socket/mdc_provider.dart';
import 'package:flutter_deer/util/speak/tts_manger.dart';
import 'package:flutter_deer/util/user_config_manager.dart';
import 'package:get/get.dart';

import '../../../util/print/data/order_type_option.dart';
import '../../../util/print/data/print_link_type.dart';
import '../../../util/toast_utils.dart';
import 'cashier_page_provider.dart';
import 'common_http_provider.dart';

class MqttHandler extends BaseNetProvider {
  final mCashierProvider = Get.find<CashierPageProvider>();
  final httpProvider = Get.find<CommonHttpProvider>();
  final mPrinter = Get.find<PrintEngineManager>();
  final mSpeaker = Get.find<TtsEngineManager>();
  final shiftProvider = Get.find<TurnShiftProvider>();
  final mdcProvider = Get.find<MdcProvider>();

  // 消费Handler
  Future<void> onConsume(MqttMsgModel msg) async {
    switch (msg.type) {
      case 'RECEIPT_SETTING_NOTICE': //小票设置通知
        httpProvider.getPrintStyle(msg.subType);
        mSpeaker.speak('小票设置已更新', toast: true);
        break;
      case 'ORDER_PRINT_NOTICE': //打印通知
        try {
          final data = jsonDecode(msg.msgContent) as Map<String, dynamic>?;
          if (data == null) {
            return;
          }

          // 判断是否打印
          if (data['isPrint'] == false) {
            return;
          }

          // 如果是预付订单，刷新列表
          final advanceOrder = data['advanceOrder'] == 1;
          if (advanceOrder) {
            mCashierProvider.requestAdvanceOrderStatisticsPage();
          }


          // 提取订单相关信息
          final orderId = '${data['orderId']}';
          final orderCode = '${data['orderCode']}';
          final orderStatus = getIntFromJson(data, 'orderStatus');
          final orderType = getIntFromJson(data, 'orderType');
          final staffName = '${data['staffName']}';
          final staffId = '${data['staffId']}';
          final shelfNo = '${data['shelfNo']}';
          final clientType = '${data['clientType']}';
          final payTypeList = getListFromJson(data, 'payTypeList', []);
          final paymentModeIdList = getListFromJson(data, 'paymentModeIdList', []);
          final clientSn = '${data['clientId']}';
          final orderRefundIds = getListFromJson(data, 'orderRefundIds', []);

          // 构建日志信息
          final logInfo = "[orderCode]=${orderCode}  " +
              "[orderId]=${orderId}  " +
              "[clientSn]=${clientSn}  " +
              "[clientType]=${clientType}  " +
              "[shelfNo]=${shelfNo}  " +
              "[payTypeList]=${payTypeList}  " +
              "[staffName]=${staffName}  " +
              "[paymentModeIdList]=${paymentModeIdList}  " +
              "[orderStatus]=${OrderPayStatus.getDesc(orderStatus)}  ";

          if (orderStatus != OrderPayStatus.REFUNDED && orderStatus != OrderPayStatus.PART_REFUNDED && orderStatus != OrderPayStatus.FINISH) {
            print('限制打印：退款中，等待推送再次打印 $logInfo');
            Toast.show("限制打印：退款中 不打印");
            return;
          }

          if (orderType == OrderTypeOption.oilStore.typeId) {
            print('限制打印：[主单]不打印不播报 $logInfo');
            return;
          }

          //是否是退款流程
          final isRefund = orderStatus > OrderPayStatus.FINISH;

          final printStyle = PrintLinkType.getPrintLinkTypeByOrderType(orderType, orderStatus);

          final canPrint = await handlePrint(orderType, clientSn, clientType, logInfo, orderId, isRefund, printStyle, shelfNo, paymentModeIdList, payTypeList, staffName, staffId);

          final canSpeak = await handleSpeak(orderType, clientSn, clientType, logInfo, orderId, isRefund, printStyle, shelfNo, paymentModeIdList, payTypeList, staffName, staffId);

          if (canPrint || canSpeak) {
            httpProvider.printTicket(orderId, success: (mapEntry) {
              print('canPrint：$canPrint canSpeak：$canSpeak ');
              if (canSpeak) {
                final speakStyle = mSpeaker.getSpeakStyleDataByOrderType(orderType);
                final speakContent = speakStyle?.replaceSpeakContent(mapEntry, advanceOrder: advanceOrder) ?? '';
                mSpeaker.speak(speakContent);
              }
              if (canPrint) {
                mPrinter.printTicket(mapEntry, printStyle);
              }
            });
          }
        } catch (e, s) {
          print('------>>> [MQTT] 处理订单状态消息异常: $e\n$s');
        }
        break;
      case 'PAYMENT_NOTICE': //支付方式通知
        break;
      case 'MERCHANT_ORDER_CONFIG': //订单配置通知
        break;
      case 'EMPLOYEE_PERFORMANCE_ENERGY': //员工绩效 消费
      case 'EMPLOYEE_PERFORMANCE_STORED': //员工绩效 储值
      case 'EMPLOYEE_AT_WILL': //员工绩效 通付
        mCashierProvider.getEmployeeConfig();
        break;
      case 'MERCHANT_USER_NOTICE': //员工变更通知
        break;
      case 'PRODUCT_NOTICE': //拉取油枪油号
        requestNetwork<List<GetConfigGunsEntity>>(Method.post, url: HttpApi.getOilGunConfig, onSuccess: (data) {
          UserConfigManager.setOilGuns(data!);
          mdcProvider.setGunPriceByGunNos(data);
        });
        break;
      case 'PULL_DATA_NOTICE': //拉取日志
        break;
      case 'CONVENIENCE_STORE': //便利店推送
        break;
      case 'DATA_PERMISSIONS': //访客模式
        break;
      case 'ORDER_MIX_NOTICE': //移动支付成功推送
        // 解析 msgContent
        /*{
            "clientType": "SaaSspj",
            "clientId": "123456789",
            "orderId": "1000200000453609141",
            "orderCode": "212025082853963876",
            "orderFinanceId": "1000200000453609143"
        }*/
        final msgContent = jsonDecode(msg.msgContent) as Map<String, dynamic>?;
        mCashierProvider.orderMqttId.value = msgContent?['orderFinanceId']?.toString() ?? '';
        break;
      case 'COUPON_USE_NOTICE': //券核销成功推送
        break;
      case 'ORDER_STATUS_CHANGE_NOTICE': //订单新增 未结算或者 结算中 推送 pos专用
        break;
      case 'ENERGY_ORDER_SYNC': //订单新增推送
        try {
          final data = jsonDecode(msg.msgContent) as Map<String, dynamic>?;
          if (data == null) {
            return;
          }
          final energyOrderId = data['energyOrderId']?.toString();
          final energyOrderStatus = data['energyOrderStatus'];
          if (energyOrderId == null || energyOrderId.isEmpty) {
            return;
          }
          if (energyOrderStatus is! int) {
            return;
          }
          AppOrderBean.updateOrderStatusById(energyOrderId, energyOrderStatus);

          // 如果是预付订单，刷新列表
          if (energyOrderStatus == OrderOilStatus.DONE) {
            mCashierProvider.requestAdvanceOrderStatisticsPage();
          }
        } catch (e, s) {
          print('------>>> [MQTT] 处理订单状态消息异常: $e\n$s');
        }
        break;
      case 'ZERO_TUBE': //获取零管配置
        if (msg.subType == 'ZERO_TUBE') {
          final data = jsonDecode(msg.msgContent) as Map<String, dynamic>?;
          if (data == null) {
            return;
          }
          final zeroTubeConfig = AppZeroModConfig.fromJson(data);
          zeroTubeConfig.save();
          Toast.show('零管配置已更新');
          mSpeaker.speak('零管配置已更新');
        }
        //{
        //  "shiftId": "1000200000462648134",
        //  "sn": "123456789",
        //  "taskId": "1000200000478542010",
        //  "shiftNo": "2025090402",
        //  "mchCode": "NY101171184177"
        // }
        if (msg.subType == 'BATCH_CER_SUCCESS') {
          //如果是本机+是主机+是本商户 才执行打印
          final data = jsonDecode(msg.msgContent) as Map<String, dynamic>?;
          final shiftId = '${data?['shiftId']}';
          final sn = '${data?['sn']}';
          if (sn == SpUtil.getString(Constant.snCode)) {
            shiftProvider.printShift(shiftId, (data) {
              if (data != null) {
                print('班结打印成功');
                mPrinter.printShift(data, PrintLinkType.WORK_CLASS_KNOT_TICKET_CONFIG);
              }
            });
          }
        }
        //dataMsg.data?.let {
        //    val jsonObject = JSONObject(it)
        //    val taskId = jsonObject.optString("taskId")
        //    val sn = jsonObject.optString("sn")
        //    //如果是本机+是主机+是本商户 才执行打印
        //    if (sn == AppUtils.getSN()) {
        //        getBatchVerificationResult(taskId)
        //    }
        //    ToastUtil.showToastDebug("批量核销成功=$it")
        //}
        if (msg.subType == 'BATCH_VERIFICATION_SUCCESS') { //批量核销成功
          //如果是本机+是主机+是本商户 才执行打印
          final data = jsonDecode(msg.msgContent) as Map<String, dynamic>?;
          final taskId = '${data?['taskId']}';
          final sn = '${data?['sn']}';
          if (sn == SpUtil.getString(Constant.snCode)) {
            // mCashierProvider.getBatchVerificationResult(taskId);
          }
        }

        break;
      case 'MERCHANT_USER_CARD_VERSION_NOTICE': //获取用户卡版本号
        break;
      case 'ENERGY_ORDER_UPLOAD_NOTICE': //新增油单推送
        break;
      case 'PREFERENTIAL_CONFIG': //获取充值额外赠送
        break;
      case 'ORDER_OFFLINE_DISCOUNTS': //线下优惠配置
        break;
      case 'ADJUST_PRICE_TASK_NOTICE': //调价任务推送
        switch (msg.subType) {
          case 'PENDING_REVIEW':
            Toast.show('调价任务待复核');
            mSpeaker.speak('调价任务待复核');
            break;
          case 'ALREADY_REJECT':
            Toast.show('调价任务已驳回');
            mSpeaker.speak('调价任务已驳回');
            break;
          case 'ALREADY_EFFECTIVE':
          case 'PENDING_EFFECTIVE':
            Toast.show('收到新的调价任务');
            mSpeaker.speak('收到新的调价任务');
            break;
          case 'ALREADY_CANCEL':
            Toast.show('调价任务已撤销');
            mSpeaker.speak('调价任务已撤销');
            break;
          case 'EXPIRED':
            Toast.show('调价任务已过期');
            mSpeaker.speak('调价任务已过期');
            break;
        }
        break;
      case 'HANDOVER_COMPLETED_NOTICE': //交班完成通知
        final data = jsonDecode(msg.msgContent) as Map<String, dynamic>?;
        if (data == null) {
          return;
        }
        final handOverBean = CurrentShiftEntity.fromJson(data);
        handOverBean.save();
        Toast.show('班次已经更新 ${handOverBean.workCycleCode}');
        mSpeaker.speak('班次已经更新');
        break;
      default:
        break;
    }
  }

  // 在类外部或工具类中添加以下函数
  int getIntFromJson(Map<String, dynamic> json, String key, [int defaultValue = 0]) {
    final value = json[key];
    if (value is int) {
      return value;
    } else if (value is String) {
      return int.tryParse(value) ?? defaultValue;
    }
    return defaultValue;
  }

  String getStringFromJson(Map<String, dynamic> json, String key, [String defaultValue = '']) {
    final value = json[key];
    return value?.toString() ?? defaultValue;
  }

  List<String> getListFromJson(Map<String, dynamic> json, String key, [List<String> defaultValue = const []]) {
    final value = json[key];
    return value is List<String> ? value : defaultValue;
  }

  // 处理打印
  Future<bool> handlePrint(
    int orderType,
    String clientSn,
    String clientType,
    String logInfo,
    String orderId,
    bool isRefund,
    PrintLinkType printStyle,
    String shelfNo,
    List<String> paymentModeId,
    List<String> payType,
    String staffName,
    String staffId,
  ) async {
    //打印总开关
    if (!mPrinter.rxIsOpenPrint.value) {
      print('限制打印：打印总开关关闭 $logInfo');
      // Toast.show("限制打印：打印总开关未开启");
      return false;
    }

    // 1、判断联数
    if (printStyle.linkType == PrintCouplet.NONE.typeCode) {
      print('限制打印：联数 ${printStyle.dec} $logInfo');
      return false;
    }

    // 退款非本机

    // 2、判断打印来源 todo refundList 本机退款处理 本机暂不支持退款
    final isSelf = clientSn == SpUtil.getString(Constant.snCode);
    final isSaasClient = clientType != 'SaaSxcx';
    // 2.1本机支付
    if (isSelf && !mPrinter.rxIsOpenPrintByClient.contains(BroadcastType.localStore.indexKey)) {
      //AppLog.e(TAG, "限制${log}：本机关闭 $logInfo")
      print('限制打印：本机关闭 $logInfo');
      return false;
    }
    // 2.2商户端非本机
    if (!isSelf && isSaasClient && !mPrinter.rxIsOpenPrintByClient.contains(BroadcastType.otherStore.indexKey)) {
      print('限制打印：商户端非本机关闭 $logInfo');
      return false;
    }
    // 2.3车主端
    if (!isSaasClient && !mPrinter.rxIsOpenPrintByClient.contains(BroadcastType.driverMini.indexKey)) {
      print('限制打印：车主端关闭 $logInfo');
      return false;
    }

    // 3、判断枪号
    if (mPrinter.rxIsOpenPrintByGun.isNotEmpty && !mPrinter.rxIsOpenPrintByGun.contains(shelfNo)) {
      print('限制打印：[shelfNo]枪号不可打印 $logInfo');
      return false;
    }

    // 4、判断支付方式
    if (mPrinter.rxIsOpenPrintByPayType.isNotEmpty && paymentModeId.isNotEmpty && paymentModeId.any((element) => !mPrinter.rxIsOpenPrintByPayType.contains(element))) {
      print('限制打印：$payType 不可打印 $logInfo');
      return false;
    }

    // 通付+银行卡支付不打印

    // 5、判断员工
    if (mPrinter.rxIsOpenPrintByEmployee.isNotEmpty && staffId.isNotEmpty && !mPrinter.rxIsOpenPrintByEmployee.contains(staffId)) {
      print('限制打印：$staffName ($staffId) 不可打印 $logInfo');
      return false;
    }

    return true;
  }

  // 处理播报
  Future<bool> handleSpeak(
    int orderType,
    String clientSn,
    String clientType,
    String logInfo,
    String orderId,
    bool isRefund,
    PrintLinkType printStyle,
    String shelfNo,
    List<String> paymentModeId,
    List<String> payType,
    String staffName,
    String staffId,
  ) async {
    // 1、播报总开关
    if (!mSpeaker.rxIsOpen.value) {
      print('限制播报：播报总开关关闭 $logInfo');
      return false;
    }

    // 2、按来源
    final isSelf = clientSn == SpUtil.getString(Constant.snCode);
    final isSaasClient = clientType != 'SaaSxcx';
    // 2.1本机支付
    if (isSelf && !mSpeaker.rxSelectOpenByClient.contains(BroadcastType.localStore.indexKey)) {
      print('限制播报：本机关闭 $logInfo');
      return false;
    }
    // 2.2商户端非本机
    if (!isSelf && isSaasClient && !mSpeaker.rxSelectOpenByClient.contains(BroadcastType.otherStore.indexKey)) {
      print('限制播报：商户端非本机关闭 $logInfo');
      return false;
    }
    // 2.3车主端
    if (!isSaasClient && !mSpeaker.rxSelectOpenByClient.contains(BroadcastType.driverMini.indexKey)) {
      print('限制播报：车主端关闭 $logInfo');
      return false;
    }

    // 3、按枪号
    if (mSpeaker.rxSelectOpenByNzl.isNotEmpty && !mSpeaker.rxSelectOpenByNzl.contains(shelfNo)) {
      print('限制播报：[shelfNo]枪号不可播报 $logInfo');
      return false;
    }

    // 4、按员工
    if (mSpeaker.rxSelectOpenByUserIds.isNotEmpty && staffId.isNotEmpty && !mSpeaker.rxSelectOpenByUserIds.contains(staffId)) {
      print('限制播报：$staffName ($staffId) 不可播报 $logInfo');
      return false;
    }

    // 5、按业务 @BusinessTypeSelect
    if (mSpeaker.rxSelectOpenByBusiness.isNotEmpty && orderType != 0) {
      return mSpeaker.canSpeakByOrderType(orderType, logInfo);
    }

    return true;
  }
}
